//#include <string.h>
#include <math.h>
#include "menu.h"
#include "user.h"
#include "message.h"
#include "bit8.h"
#include "chain.h"
//.............. CODING ..........
static chain chCoding;
static chain chAll;
double ReturnR(double u,double v) { return sqrt(u*u+v*v); }
double ReturnU(double u,double v) { return u+0*v; }
double ReturnV(double u,double v) { return v+0*u; }
static chain chR(ReturnR," ");
static chain chU(ReturnU," ");
static chain chV(ReturnV," ");
static chain ch1,ch2,ch3;
extern int (*MinMaxFun)()=0;

void ChangeChain() {
   SignRad=0;
   switch (FormDoe) {
   case dftAnnular:
      SignRad=1;
      ch1=chFun(chR);
      chAll=chCoding(ch1);
      break;
   case dftCylindrical:
      ch1=chFun(chU);
      chAll=chCoding(ch1);
      break;
   case dftCrossed:
      ch1=chFun1(chU);
      ch2=chFun2(chV);
      ch3=chFun(ch1,ch2);
      chAll=chCoding(ch3);
      break;
   case dftNonSymmetric:
      chAll=chCoding(chFun);
      break;
   default:
      strbox(" What you want in ChangeChain");
   }
}

int init_gen(DoeFormType form) {
//   sprintf(TmpStr," w=%f h=%f s=%f",DoeWidth, DoeHight, DoeStep);
//   strbox(TmpStr);
   int ret;
   switch (form) {
   case dftAnnular:
      ret=round(DoeWidth/2, DoeStep, chAll, &HorSize, &VerSize);
      break;
   case dftCylindrical:
      ret=cylindr(DoeWidth, DoeHight, DoeStep, chAll, &HorSize, &VerSize);
      break;
   case dftCrossed:
      ret=rectan3(DoeWidth, DoeHight, DoeStep, chAll, chFun1, chFun2,
	      &HorSize, &VerSize);
      break;
   case dftNonSymmetric:
      ret=rectan1(DoeWidth, DoeHight, DoeStep, chAll, &HorSize, &VerSize);
      break;
   default:
      strbox(" wrong FormType in INIT_GEN");
      ret=1;
   }
   return ret;
}

//........................................
int CodingEmptyFun() {
   SignRad=0;
   chAll=chFun;
   if(init_gen(FormDoe))  return 1;
   MaxValue=MaxValueDoe;
   MinValue=MinValueDoe;
   return 0;
}
void CodingEmpty() {
   MinMaxFun=CodingEmptyFun;
   Doe=DoeDoe;
   MessageCoding("Coding - None", " ");
   UndoMenu(2) ;
}
//........................................
double fmod_(double a, double b) {
   int i=a/b;
   double t=a-i*b;
   if(t<0)  t+=b;
   return t;
}
static double M2piOffset, M2piStep=0;
double PhaseTo2pi(double p) {
   double ret;
   if(p>=MinValueDoe)
      ret=fmod_((p+M2piOffset),M2piStep);
   else  ret=-1;
   return ret;
}
int CodingPhaseTo2piFun() {
   chCoding=chain(PhaseTo2pi,"2piM");
   M2piOffset=M2piStep-fmod_(MaxValueDoe,M2piStep)-.001;
   chAll=chCoding(chFun);
   SignRad=0;
   if(init_gen(FormDoe))  return 1;
   MaxValue=M2piStep;
   MinValue=0;
   return 0;
}
void CodingPhaseTo2pi()  {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }
   static char *name={"  Coding : Phase to 2piM  "};
   char *names[]={"  Enter M     : " };
   char *Def[]={"1        "};
   if(!sedit(25,5,1,names,TmpPar,Def,name))  return ;
   float m;
   sscanf(TmpPar[0],"%f \0",&m);
   sprintf(Def[0],"%f",m);

   M2piStep=2*M_PI*m;

   MinMaxFun=CodingPhaseTo2piFun;
   Doe=Phase;
   sprintf(TmpStr,"  M=%f",m);
   MessageCoding("Coding - Phase to 2pM", TmpStr);
   UndoMenu(2) ;
}
//........................................
static double M__UF, M__VF;

double PhaseToAmplitude(double u,double v,double a)
   { return cos( a-2*M_PI*(M__UF*u+M__VF*v) );}
int CodingPhaseToAmplitudeFun() {
   chCoding=chain(PhaseToAmplitude,"kodir  aa");
   ChangeChain();

   if(init_gen(dftNonSymmetric))  return 1;
   MaxValue= 1;
   MinValue= -1;
   return 0;
}
void CodingPhaseToAmplitude() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }
   static char *name={"Coding: Phase to Ampl with Carrier"};
   char *names[]={
		  "U-Frequency (1/mm):",
		  "V-Frequency (1/mm):"
		  };
   char *Def[]={"3        ","5        "};
   if(!sedit(25,5,2,names,TmpPar,Def,name))  return ;
   sscanf(TmpPar[0],"%lf \0",&M__UF);
   sscanf(TmpPar[1],"%lf \0",&M__VF);
   sprintf(Def[0],"%f",M__UF);
   sprintf(Def[1],"%f",M__VF);

   MinMaxFun=CodingPhaseToAmplitudeFun;
   Doe=Amplitude;
//   Doe=Phase;
   sprintf(TmpStr,"Wu=%f  Wv=%f",M__UF,M__VF);
   MessageCoding("Coding-to Ampl with Carrier", TmpStr);
   UndoMenu(2) ;
}
//........................................

double SignPhase(double a){
   if(a<0) return M_PI;
   else    return 0;
}
int CodingAmplToSignPhaseFun() {
   chCoding=chain(SignPhase,"sign phase");
   chAll=chCoding(chFun);
   SignRad=0;
   if(init_gen(FormDoe))  return 1;
   MaxValue=M_PI;
   MinValue=0;
   return 0;
}
void CodingAmplToSignPhase() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }

   MinMaxFun=CodingAmplToSignPhaseFun;
   Doe=Phase;
   MessageCoding("Coding - to Phase {0,pi}", " ");
   UndoMenu(2) ;
}
//........................................

static float f1,f2;
void kirk0_init(double,double,double,double);
double kirk0(double,double,double);
void kirk1_init(double,double,double,double);
double kirk1(double,double,double);
void hsu1_init(double,double,double,double);
double hsu1(double,double,double);
void hsu0_init(double,double,double,double);
double hsu0(double,double,double);

int CodingAmplToPhaseCarrierFunk0() {
   kirk0_init(MinValueDoe, MaxValueDoe, f1, f2);
   chCoding=chain(kirk0,"kirk0");
   ChangeChain();
   if(init_gen(dftNonSymmetric))  return 1;

   MaxValue=2*M_PI+2.38;
   MinValue=-2.38;
   return 0;
}
int CodingAmplToPhaseCarrierFunk1() {
   kirk1_init(MinValueDoe, MaxValueDoe, f1, f2);
   chCoding=chain(kirk1,"kirk1");
   ChangeChain();
   if(init_gen(dftNonSymmetric))  return 1;
   MaxValue=2*M_PI+1.84;
   MinValue=-1.84;
   return 0;}
int CodingAmplToPhaseCarrierFunh0() {
   hsu0_init(MinValueDoe, MaxValueDoe, f1, f2);
   chCoding=chain(hsu0,"hsu0");
   ChangeChain();
   if(init_gen(dftNonSymmetric))  return 1;

   MinValue=-M_PI;
   MaxValue=3*M_PI;
   return 0;
}
int CodingAmplToPhaseCarrierFunh1() {
   hsu1_init(MinValueDoe, MaxValueDoe, f1, f2);
   chCoding=chain(hsu1,"hsu1");
   ChangeChain();
   if(init_gen(dftNonSymmetric))  return 1;

   MinValue=-M_PI;
   MaxValue=3*M_PI;
   return 0;
}
void CodingAmplToPhaseCarrier() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }
   static char *name={"  Coding : Ampl to Phase with Carrier"};
   int wave, order;
   char *names[]={
		  "U-Frequence (1/mm):",
		  "V-Frequence (1/mm):",
		  "Useful       Order:",
		  "Rect/sin     (1/0):"
		  };
   char *Def[]={
		"30            ",
		"30            ",
		"0             ",
		"0             "
		};
   if(!sedit(25,5,4,names,TmpPar,Def,name))  return ;
   sscanf(TmpPar[0],"%f \0",&f1);
   sscanf(TmpPar[1],"%f \0",&f2);
   sscanf(TmpPar[2],"%d \0",&wave);
   sscanf(TmpPar[3],"%d \0",&order);
   sprintf(Def[0],"%f",f1);
   sprintf(Def[1],"%f",f2);
   if((wave==0)&&(order==0)) { MinMaxFun=CodingAmplToPhaseCarrierFunk0; }
   if((wave==1)&&(order==0)) { MinMaxFun=CodingAmplToPhaseCarrierFunh0; }
   if((wave==0)&&(order==1)) { MinMaxFun=CodingAmplToPhaseCarrierFunk1; }
   if((wave==1)&&(order==1)) { MinMaxFun=CodingAmplToPhaseCarrierFunh1; }
   Doe=Phase;
   sprintf(TmpStr,"Wu=%f Wv=%f",f1,f2);
   MessageCoding("Coding -Kirk-Jones Method", TmpStr);
   UndoMenu(2) ;
}

static double AAC_f1,AAC_f2;
double kodir(double u,double v,double a)
   { return a*cos(2*M_PI*(AAC_f1*u+AAC_f2*v));}
int CodingAmplToAmplCarrierFun() {
   chCoding=chain(kodir,"kodir");
   ChangeChain();

   if(init_gen(dftNonSymmetric))  return 1;
   double p1=fabs(MaxValueDoe), p2=fabs(MinValueDoe);
   MaxValue= (p1>p2) ? p1 : p2;
   MinValue= (-p1<-p2) ? -p1 : -p2;
   return 0;
}
void CodingAmplToAmplCarrier() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }
   static char *name={"  Coding : Ampl to Ampl with Carrier"};
   char *names[]={"U-Frequency (1/mm):",
		  "V-Frequency (1/mm):"};
   char *Def[]={
		"30       ",
		"50       "
		};
   if(!sedit(25,5,2,names,TmpPar,Def,name))  return ;
   sscanf(TmpPar[0],"%lf \0",&AAC_f1);
   sscanf(TmpPar[1],"%lf \0",&AAC_f2);
   sprintf(Def[0],"%f",AAC_f1);
   sprintf(Def[1],"%f",AAC_f2);

   MinMaxFun=CodingAmplToAmplCarrierFun;
   Doe=Amplitude;
//   Doe=Phase;
   sprintf(TmpStr,"Wu=%f  Wv=%f",AAC_f1,AAC_f2);
   MessageCoding("Coding-to Ampl with Carrier", TmpStr);
   UndoMenu(2) ;
}
//........................................
double unsign(double a){ return fabs(a); }
int CodingAmplToAbsAmplFun() {
   chCoding=chain(unsign,"unsign");
   chAll=chCoding(chFun);
   SignRad=0;
   if(init_gen(FormDoe))  return 1;
   double p1=fabs(MaxValueDoe), p2=fabs(MinValueDoe);
   MaxValue= (p1>p2) ? p1 : p2;
   MinValue= (p1<p2) ? p1 : p2;
   if(MinValueDoe<0 && MaxValueDoe>0)  MinValue=0;
   return 0;
}
void CodingAmplToAbsAmpl() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }

   MinMaxFun=CodingAmplToAbsAmplFun;
   Doe=Amplitude;
//   Doe=Phase;
   MessageCoding("Coding-to Absolute Amplitude", " ");
   UndoMenu(2) ;
}
//........................................

double intens(double a){return a*a; }
int CodingAmplToIntensityFun() {
   chCoding=chain(intens,"Intensity");
   chAll=chCoding(chFun);
   SignRad=0;
   if(init_gen(FormDoe))  return 1;
   double p1=MaxValueDoe*MaxValueDoe, p2=MinValueDoe*MinValueDoe;
   MaxValue= (p1>p2) ? p1 : p2;
   MinValue= (p1<p2) ? p1 : p2;
   if(MinValueDoe<0 && MaxValueDoe>0)  MinValue=0;
   return 0;
}
void CodingAmplToIntensity() {
   if(DoeDoe==Undefine) { strbox("DOE must be defined"); return; }

   MinMaxFun=CodingAmplToIntensityFun;
   Doe=Intensity;
//   Doe=Phase;
   MessageCoding("Coding - to Intensity", " ");
   UndoMenu(2) ;
}
